package com.kaifamiao.month04.day18;


import java.util.*;

public class MyList extends AbstractList implements List, Cloneable {

    private Object[] dataList; // 底层是数组
    private final Object[] EMPTY_DATALIST = {}; // 默认为空

    private int modCount;

    private int count;

    public MyList() {
        this(10);
    }

    /**
     * 初始化一个指定容量的数组
     * @param capacity 指定的容量大小
     */
    public MyList(int capacity) {
        if (capacity > 0) {
            dataList = new Object[capacity];
        } else if (capacity == 0) {
            dataList = EMPTY_DATALIST;
        } else {
            throw new IllegalArgumentException("非法输入" + capacity);
        }
    }

    @Override
    public Object get(int index) {
        checkIndex(index);
        return dataList[index];
    }

    /**
     * 检查输入的下标
     *
     * @param index 检查的下标
     */
    private void checkIndex(int index) {
        if (index >= count || index < 0) {
            throw new IndexOutOfBoundsException("错误的的位置：" + index);
        }
    }

    @Override
    public int size() {
        return count;
    }

    public boolean add(Object element) {
        if (count == dataList.length) {
            grow();
        }
        dataList[count++] = element;
        modCount++;
        return true;
    }

    public void add(int index, Object element) {
        checkIndex(index);
        if (count == dataList.length) {
            grow();
        }
        System.arraycopy(dataList, index, dataList, index + 1, count - index);
        dataList[index] = element;
        modCount++;
        count++;
    }

    private void grow() {
        dataList = Arrays.copyOf(dataList, count << 1);
    }

    public Object remove(int index) {
        checkIndex(index);
        Object obj = get(index);
        System.arraycopy(dataList, index + 1, dataList, index, count - index - 1);
        dataList[count--] = null;
        modCount++;
        return obj;
    }

    public Object set(int index, Object element) {
        checkIndex(index);
        Object oldElement = get(index);
        dataList[index] = element;
        return oldElement;
    }

    public int indexOf(Object element) {
        for (int i = 0; i < count; i ++) {
            if (element == null) {
                if (dataList[i] == null) {
                    return i;
                }
            } else {
                if (element.equals(dataList[i])) {
                    return i;
                }
            }
        }
        return -1;
    }

    public int lastIndexOf(Object element) {
        for (int i = count; i >= 0; i--) {
            if (element == null) {
                if (dataList[i] == null) {
                    return i;
                }
            } else {
                if (element.equals(dataList[i])) {
                    return i;
                }
            }
        }

        return -1;
    }

    public boolean contains(Object element) {
        for (Object dl : dataList) {
            if (element == null) {
                if (dl == null) {
                    return true;
                }
            } else {
                if (element.equals(dl)) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean remove(Object element) {
        if (indexOf(element) < 0) {
            return false;
        } else {
            remove(indexOf(element));
            return true;
        }
    }

    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public Iterator iterator() {
        return new MyListIterator( );
    }

    private class MyListIterator implements Iterator {

        private int current;
        private int index = -1;
        private int exceptedCount = modCount;

        @Override
        public boolean hasNext() {
            return current != count;
        }
        @Override
        public Object next() {
            checkExceptedCount();
            if (current >= count) {
                throw new NoSuchElementException();
            }
            return dataList[index = current++];
        }


        public void remove() {
            if (index == -1) {
                throw new IllegalStateException();
            }
            checkExceptedCount();
            MyList.this.remove(index);
            exceptedCount = modCount;
            current = index;
            index = -1;
        }

        private void checkExceptedCount() {
            if (exceptedCount != modCount) {
                throw new ConcurrentModificationException();
            }
        }
    }
}
